home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-06-04 | 17.5 KB | 678 lines | [TEXT/MPS ] |
- /*
- * File: RequestDispatcher.cp
- *
- * Contains: xxx put contents here xxx
- *
- * Written by: Rick Violet
- *
- * Copyright: © 1992-1994 by Apple Computer, Inc., all rights reserved.
- *
- * Change History (most recent first):
- *
- * <7> 1/28/94 CMW String utilities have moved to TextUtils.h.
- * <2> 4/15/93 RV Fix Memory Leak in DispatchCustomRequest
- * 11/18/92 RV xxx put comment here xxx
- *
- * To Do:
- */
-
- #include <PLStringFuncs.h>
- #include <SysEqu.h>
- #include <Strings.h>
- #include <TextUtils.h>
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif __MEMORY__
-
- #ifndef __RESOURCES__
- #include <Resources.h>
- #endif __RESOURCES__
-
- #ifndef __GESTALTEQU__
- #include <GestaltEqu.h>
- #endif __GESTALTEQU__
-
- #ifndef __Application__
- #include "Application.h"
- #endif __Application__
-
- #ifndef __RequestDispatcher__
- #include "RequestDispatcher.h"
- #endif __RequestDispatcher__
-
- #ifndef __ProcessServices__
- #include "ProcessServices.h"
- #endif __ProcessServices__
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // Global Variables
- //—————————————————————————————————————————————————————————————————————————————————————
- RequestDispatcher* gTheRequestDispatcher;
- extern Application* gTheApplication;
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // External Routines
- //—————————————————————————————————————————————————————————————————————————————————————
- extern void TerminalError(short errResID, short errCode);
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::RequestDispatcher - constructor.
- //—————————————————————————————————————————————————————————————————————————————————————
- RequestDispatcher::RequestDispatcher()
- {
- const long gestaltAppleEventsManager101 = 1;
-
- OSErr tErr;
- long tGestaltResult;
-
- fRequestQueue = nil;
- fServices = nil;
- fReqBeingProcessed = nil;
- fRunningInSystem7 = false;
-
- //———— Construct a Queue for incoming requests
- fRequestQueue = new List();
- if( fRequestQueue == nil )
- {
- TerminalError( kDispatcherErrStrings, kReqQueueConstructErr );
- }
-
- //———— Construct a Queue for Services
- fServices = new List();
- if( fServices == nil )
- {
- TerminalError( kDispatcherErrStrings, kServQueueConstructErr );
- }
-
-
- //———— Determine if we're running Post System 6 system software
- if( Gestalt( gestaltSystemVersion, &tGestaltResult) == noErr )
- {
- fRunningInSystem7 = ( tGestaltResult >= 7 );
- }
-
- //———— Make sure that AppleEvents are availible, in the right version
- tErr = Gestalt( gestaltAppleEventsAttr, &tGestaltResult);
-
- //———— Check the gestaltAppleEventsPresent bit
- if( !(tGestaltResult & ( 1 << gestaltAppleEventsPresent )) )
- {
- TerminalError( kDispatcherErrStrings, kAppleEventVersionErr );
- }
-
- //———— Check the gestaltAppleEventsManager101 bit
- if( !(tGestaltResult & ( 1 << gestaltAppleEventsManager101 )) )
- {
- TerminalError( kDispatcherErrStrings, kAppleEventVersionErr );
- }
-
- //———— Install all the Request Handlers
- ConstructAllServiceObjects();
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::~RequestDispatcher - destructor.
- //—————————————————————————————————————————————————————————————————————————————————————
- RequestDispatcher::~RequestDispatcher()
- {
- //———— Delete all the Service Objects
- if( fServices )
- {
- fServices->DisposeAll();
- delete fServices;
- }
-
- //———— Delete all the Queued Requests
- if( fRequestQueue )
- {
- fRequestQueue->DisposeAll();
- delete fRequestQueue;
- }
-
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::ConstructAllServices - Install all the Service objects.
- //
- // This method calls the constructor for each Request handler
- // and installs a pointer to it in the Queue of Services
- //
- // You must construct and install your Custom Request Handlers here
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::ConstructAllServiceObjects()
- {
- Service* tService;
-
- //———— if the List for containing the services does not exist,
- //———— bail out so we don't crash.
- if( fServices == nil )
- {
- return;
- }
-
- //———— Construct the service object : ProcessNamesListService
- tService = new ProcessNamesListService();
- if( tService )
- {
- fServices->AddAsLast( tService );
- }
-
- //———— Construct the service object : FrontProcessNameService
- tService = new FrontProcessNameService();
- if( tService )
- {
- fServices->AddAsLast( tService );
- }
-
- //———— Construct the service object : PartitionSizeService
- tService = new PartitionSizeService();
- if( tService )
- {
- fServices->AddAsLast( tService );
- }
-
- //———— Construct the service object : FreeMemService
- tService = new FreeMemService();
- if( tService )
- {
- fServices->AddAsLast( tService );
- }
-
- //———— Construct the service object : ReadByteService
- tService = new ReadByteService();
- if( tService )
- {
- fServices->AddAsLast( tService );
- }
-
- //———— Construct the service object : ReadBlockService
- tService = new ReadBlockService();
- if( tService )
- {
- fServices->AddAsLast( tService );
- }
-
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::DoOneRequest - Process first pending Request in the queue.
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::DoOneRequest()
- {
- Request* tReq;
-
- //———— Is there an element in the Queue?
- if( (fRequestQueue != nil) && (fRequestQueue->Count() > 0) )
- {
- //———— Reset any TimeOut counters which need it
- ResetAllTimeOutCounters();
-
- //———— there is a Request in the Queue
- //———— Extract it from the Queue
- tReq = (Request*)fRequestQueue->GetFirst();
-
- //———— if we got a Request object
- if( tReq )
- {
- fRequestQueue->Remove( tReq );
-
- //———— Keep track of which request is currently
- //———— being processed, so it can be canceled if needed
- fReqBeingProcessed = tReq;
-
- //———— Process the request
- if( !tReq->HasBeenCanceled() )
- {
- ProcessRequest( tReq );
- }
- tReq->SendResult();
- delete tReq;
-
- //———— No longer processing this request
- fReqBeingProcessed = nil;
- }
- }
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::QueueRequest - Puts a Request into our Queue
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::QueueRequest( Request* pReq )
- {
- //———— if this is a request to cancel a service request,
- //———— then find the service request and cancel it
- if( pReq->IsACancelRequest() )
- {
- DoCancelReq( pReq );
- delete pReq;
- }
- else
- {
- //———— This is not a request to cancel a service request
- //———— so queue it up, for processing later
- if( fRequestQueue != nil )
- {
- fRequestQueue->AddAsLast( pReq );
- }
- }
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::CancelCurrentRequest - Cancel processing of the current request
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::CancelCurrentRequest()
- {
- Request* tReq;
-
- tReq = GetCurrentRequest();
- if( tReq != nil )
- {
- tReq->CancelThisRequest();
- }
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::ProcessRequest - Process the Request
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::ProcessRequest( Request* pReq )
- {
- char* tServiceName;
-
- //———— Get the Text of the Service requested
- tServiceName = pReq->GetWhichService();
-
- //———— Check for GetToolVersion request
- if( relstring( tServiceName, (char*)kVUAEGetToolVersion, false, true ) == 0 )
- {
- DoGetToolVersReq( pReq );
- return;
- }
-
- //———— Check for GetToolServices request
- if( relstring( tServiceName, (char*)kVUAEGetServiceList, false, true ) == 0 )
- {
- DoGetToolServicesReq( pReq );
- return;
- }
-
- //———— Check for GetToolServices request
- if( relstring( tServiceName, (char*)kVUAEHasService, false, true ) == 0 )
- {
- DoServiceSupportedReq( pReq );
- return;
- }
-
- //———— Check for Initialize request
- if( relstring( tServiceName,(char*)kVUAEInitialize, false, true ) == 0 )
- {
- DoInitializeReq();
- return;
- }
-
- //———— Check for Quit request
- if( relstring( tServiceName,(char*)kVUAEQuitService, false, true ) == 0 )
- {
- gTheApplication->DoMenuCommand( kFileMenuID, kQuitItem );
- return;
- }
-
- DispatchCustomRequest( pReq );
-
- return;
-
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::DoCancelReq - do the cancel Request
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::DoCancelReq( Request* pReq )
- {
- Loop* tLoop;
- Request* tSrvReq;
-
- //———— Are we currently processing another request?
- if( CurrentlyProcessingARequest() )
- {
- //———— We are currently processing a request,
- //———— Check to see if the current request is the one to be canceled
- tSrvReq = GetCurrentRequest();
- if( tSrvReq->IsCancelRequestForThisRequest( pReq ) )
- {
- tSrvReq->CancelThisRequest();
- return;
- }
- }
-
- //———— Now check the Queue for the Request that this cancel is for.
- tLoop = new Loop( fRequestQueue );
- if( tLoop )
- {
- while( tSrvReq = (Request*)(tLoop->GetNext()) )
- {
- //———— Is this the Service Object to be canceled?
- if( tSrvReq->IsCancelRequestForThisRequest( pReq ) )
- {
- tSrvReq->CancelThisRequest();
- return;
- }
-
- }
- delete tLoop;
- }
-
-
- //———— if it was not found, then it was either never received,
- //———— or was completed and returned before the cancel request
- //———— arrived. In either case, just return an empty return value.
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::DoGetToolVersReq - return the version information
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::DoGetToolVersReq( Request* pReq )
- {
- VUList* tReturnList;
- char tText[256];
-
- tReturnList = new VUList();
- if( tReturnList )
- {
- //———— Get the Tool's Name
- GetToolName( tText );
- tReturnList->PutNthItem( tText );
-
- //———— Get the Tool's Version String
- GetToolVersionString( tText );
- tReturnList->PutNthItem( tText );
-
- pReq->SetReturnValue( tReturnList );
- }
- else
- {
- pReq->SetErrorCode( memFullErr );
- pReq->SetErrorMessage( "Out of memory?" );
- }
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::DoInitializeReq - pass initialize message to all services
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::DoInitializeReq()
- {
- Loop* tLoop;
- Service* tService;
-
- //———— Scan through the Service objects,
- //———— and inform it that we have received and initialize messagge
- tLoop = new Loop( fServices );
- if( tLoop )
- {
- while( tService = (Service*)(tLoop->GetNext()) )
- {
- //———— Call the initialize method for the service object
- tService->Initialize();
- }
- }
- delete tLoop;
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::DispatchCustomRequest - execute a custom Request
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::DispatchCustomRequest( Request* pReq )
- {
- Loop* tLoop;
- Service* tService;
- char* tServiceName;
-
- //———— Get the Text of the Service requested
- tServiceName = pReq->GetWhichService();
-
-
- if( fServices == nil )
- {
- //———— no queue object, bail out
- return;
- }
-
- tLoop = new Loop( fServices );
- if( tLoop )
- {
- while( tService = (Service*)(tLoop->GetNext()) )
- {
- //———— Is this the Service Object which can handle this request?
- if( tService->CanDoService( tServiceName ) )
- {
- //———— This is the correct Service Object,
- //———— Get the service object to process the request
- tService->ProcessRequest( pReq );
-
- //———— Reset the cursor, so beach ball is not left there
- InitCursor();
- delete tLoop;
- return;
- }
- }
- delete tLoop;
- }
-
- //———— The service which handles this request was not found
- //———— Report error and return
- pReq->SetErrorCode( errAEUnknownService );
- pReq->SetErrorMessage( "Service not found" );
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::DoGetToolServicesReq - return the list of Request names
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::DoGetToolServicesReq( Request* pReq )
- {
- Loop* tLoop;
- VUList* tReturnList;
- Service* tService;
- ScriptValue* tReturnNames;
- ScriptValue* tVal;
- char* tText;
- ValueKind tVKind;
- short tLastElement;
- short i;
-
- tReturnList = new VUList();
-
- if( tReturnList )
- {
- //———— Scan through the Service objects, and collect the
- //———— text of the service names which this tool supports
- tLoop = new Loop( fServices );
- if( tLoop )
- {
- while( tService = (Service*)(tLoop->GetNext()) )
- {
- //———— Get the service's Name text
- //———— and append it to the list
- tReturnNames = tService->GetServiceNameText();
- if( tReturnNames )
- {
- switch( tReturnNames->GetValueKind() )
- {
- case kVUListKind:
- {
- tLastElement = ((VUList*)tReturnNames)->GetCount();
- for( i = 1; i < tLastElement; i++ )
- {
- tVKind = kVUStringKind;
- ((VUList*)tReturnNames)->GetNthItem( i, tVal, tVKind );
- if( tVal )
- {
- tText = ((VUString*)tVal)->GetText();
- tReturnList->PutNthItem( tText );
- }
- }
- }
- break;
-
- default:
- {
- tText = ((VUString*)tReturnNames)->GetText();
- tReturnList->PutNthItem( tText );
- }
- break;
-
- }
- delete tReturnNames;
- }
- }
- delete tLoop;
- }
-
- //———— We have tranversed the entire list of service objects
- //———— and collected each service's name into the list
- //———— now return the list to V.U.
- pReq->SetReturnValue( tReturnList );
- }
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::DoServiceSupportedReq - return the list of Request names
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::DoServiceSupportedReq( Request* pReq )
- {
- Loop* tLoop;
- Service* tService;
- ScriptValue* tParam;
- char* tSrvText;
- ValueKind tVKind;
- OSErr tErr;
-
- //———— Get the parameter which contains the service identifier
- //———— which we want to determine if it is supported
- tVKind = kVUStringKind;
- tErr = pReq->GetNthParam( 1, tParam, tVKind );
-
- //———— Make sure we have the right type of parameter
- if( tParam == nil || tErr )
- {
- return;
- }
-
- tSrvText = ((VUString*)tParam)->GetText();
- if( tSrvText == nil )
- {
- return;
- }
-
- //———— Scan through the Service objects, and inquire if any
- //———— supports the indicated service
- tLoop = new Loop( fServices );
- if( tLoop )
- {
- while( tService = (Service*)(tLoop->GetNext()) )
- {
- //———— Ask service object if it can do this service,
- if( tService->CanDoService( tSrvText ) )
- {
- //———— We have found a service object which can handle this
- //———— request type, return true to V.U.
- pReq->SetReturnValue( true );
- return;
- }
- }
- delete tLoop;
- }
-
- //———— We have looked through the entire list of service objects
- //———— and have not found one which handles this request type
- //———— return false to V.U.
- pReq->SetReturnValue( false );
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::GetToolName
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::GetToolName( char* pText )
- {
- short tLength;
-
- //———— Get the Application name from the Low global CurApName
- PLstrcpy( (StringPtr)pText, (StringPtr)CurApName );
- p2cstr( (StringPtr)pText );
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::GetToolVersionString
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::GetToolVersionString( char* pText )
- {
- VersResRecHdl tVers;
- short tLength;
- short i;
- char* s;
- char* d;
-
- tVers = (VersResRecHdl)Get1Resource( 'vers', 1 );
- if( tVers )
- {
- HLock( (Handle)tVers );
-
- //———— Set s to point at the length byte of the short version string
- s = (*tVers)->versStr;
-
- //———— Advance s to the length byte of the long version string
- //———— which begins just after the short version string
- s += s[0] + 1;
-
- //———— Get the length of the long version string
- tLength = s[0];
-
- //———— Copy the long version string into pText
- d = pText;
- s++;
- for( i = 0; i < tLength; i++ )
- {
- *d++ = *s++;
- }
- *d = 0; //———— Terminating Null character
-
- HUnlock( (Handle)tVers );
- ReleaseResource( (Handle)tVers );
- }
- else
- {
- strcpy( pText, "Version string not availible." );
- }
- }
-
- //—————————————————————————————————————————————————————————————————————————————————————
- // RequestDispatcher::ResetAllTimeOutCounters
- //—————————————————————————————————————————————————————————————————————————————————————
- void
- RequestDispatcher::ResetAllTimeOutCounters()
- {
- Loop tLoop( fRequestQueue );
- Request* tReq;
-
- if( fReqBeingProcessed )
- {
- fReqBeingProcessed->ResetTimeOutCounter();
- }
-
- while( tReq = (Request*)tLoop.GetNext() )
- {
- tReq->ResetTimeOutCounter();
- }
-
- }